package main

import (
	"bufio"
	"bytes"
	"compress/gzip"
	"crypto/sha1"
	"encoding/gob"
	"encoding/json"
	"encoding/xml"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

var (
	firstName, lastName, s string
	i int
	f float32
	input = "56.12 / 5212 / Go"
	format = "%f / %d / %s"
)

func test1() {
	fmt.Println("Please enter you full name: ")
	fmt.Scanln(&firstName, &lastName)
	fmt.Printf("Hi %s %s!\n", firstName, lastName)
	fmt.Sscanf(input, format, &f, &i, &s)
	fmt.Println("From the string we read: ", f, i, s)
}

func test2() {
	inputReader := bufio.NewReader(os.Stdin)
	fmt.Println("Please enter some iput: ")
	input, err := inputReader.ReadString('\n')
	if err == nil{
		fmt.Printf("The input was: %s\n", input)
	}
}

func test3() {
	inputReader := bufio.NewReader(os.Stdin)
	fmt.Println("Please enter you name: ")
	input, err := inputReader.ReadString('\n')
	if err != nil {
		fmt.Println("There were errors reading, exiting program.")
		return
	}
	fmt.Printf("Your name is %s", input)
	switch input {
	case "Philip\r\n":
		fmt.Println("Welcome Philip")
	case "Chis\r\n":
		fmt.Println("Welcome Chis")
	case "Ivo\r\n":
		fmt.Println("Welcome Ivo!")
	default:
		fmt.Printf("You are not welcome here! Goodbye")
	}
}

func fileInput() {
	inputFile, inputError := os.Open("G:\\golang\\waytogo\\readAndwrite\\ReadAndWrite.md")
	if inputError != nil{
		fmt.Printf("An error occurred on opening the inputfile\n" +
			"Does the file exist?\n" +
			"Have you got access to it?\n")
		return
	}

	defer inputFile.Close()

	inputReader := bufio.NewReader(inputFile)
	for{
		inputString, readerError := inputReader.ReadString('\n')
		fmt.Printf("The input was: %s", inputString)
		if readerError == io.EOF{
			return
		}
	}
}

func test4() {
	inputFile := "G:\\golang\\waytogo\\readAndwrite\\products.txt"
	outputFile := "G:\\golang\\waytogo\\readAndwrite\\products_copy.txt"

	buf, err := ioutil.ReadFile(inputFile)
	if err != nil{
		fmt.Fprintf(os.Stderr, "File Error: %s\n", err)
	}
	fmt.Printf("%s\n", string(buf))
	err = ioutil.WriteFile(outputFile, buf, 0644)
	if err != nil{
		fmt.Fprintf(os.Stderr, "File Error: %s\n", err)
	}
}

func test5() {
	file, err := os.Open("G:\\golang\\waytogo\\readAndwrite\\products1.txt")
	if err != nil{
		return
	}

	defer file.Close()

	var col1, col2, col3 []string
	for {
		var v1, v2, v3 string
		_, err := fmt.Fscanln(file, &v1, &v2, &v3)
		if err != nil{
			break
		}
		col1 = append(col1, v1)
		col2 = append(col2, v1)
		col3 = append(col3, v1)
	}

	fmt.Println(col1)
	fmt.Println(col2)
	fmt.Println(col3)
}

func test6() {
	fName := "G:\\golang\\waytogo\\readAndwrite\\products.zip"
	var r *bufio.Reader
	fi, err := os.Open(fName)
	if err != nil{
		fmt.Fprintf(os.Stderr, "%v, Can't open %s: error: %s\n", os.Args[0], fName)
		os.Exit(1)
	}

	defer fi.Close()

	fz, err := gzip.NewReader(fi)
	if err != nil{
		r = bufio.NewReader(fi)
	}else  {
		r = bufio.NewReader(fz)
	}

	for {
		line, err := r.ReadString('\n')
		if err != nil{
			fmt.Println("Done reading file")
			os.Exit(0)
		}
		fmt.Println(line)
	}

}

func test7() {
	outputFile, outputError := os.OpenFile("G:\\golang\\waytogo\\readAndwrite\\products.txt",
		os.O_WRONLY|os.O_CREATE, 0666)
	if outputError != nil{
		fmt.Printf("An error occurred with file opening or creation\n")
		return
	}
	defer outputFile.Close()

	outputWriter := bufio.NewWriter(outputFile)
	outputString := "hello world!\n"

	for i := 0; i < 10; i++ {
		outputWriter.WriteString(outputString)
	}

	outputWriter.Flush()

}

func argstest() {
	who := "Wolfe"
	if len(os.Args) > 1{
		who += strings.Join(os.Args[1:], " ")
	}

	fmt.Println("Good Morning", who)
}

var NewLine = flag.Bool("n", false, "print newline")
const (
	Space	= " "
	Newline = "\n"
)

func flagecho() {
	//flag.PrintDefaults()
	flag.Parse()
	var s string = ""
	for i:=0; i < flag.NArg(); i++{
		if i > 0{
			s += " "
			if *NewLine{
				s += Newline
			}
		}
		s += flag.Arg(i)
	}
	os.Stdout.WriteString(s)
}

type Address struct {
	Type 	string
	City 	string
	Country string
}

type VCard struct {
	FirstName 		string
	LastName		string
	Addresses		[]*Address
	Remark			string
}

func jsontest() {
	pa := &Address{"private", "Aartselaar", "Belgium"}
	wa := &Address{"work", "Boom", "Belgium"}
	vc := VCard{"Jan", "Kersschot", []*Address{pa, wa}, "none"}

	js, _ := json.Marshal(vc)
	fmt.Printf("JSON format: %s", js)
	file, _ := os.OpenFile("G:\\golang\\waytogo\\readAndwrite\\vcard.json", os.O_CREATE|os.O_WRONLY, 0666)
	defer file.Close()
	enc := json.NewEncoder(file)
	err := enc.Encode(vc)
	if err != nil{
		log.Println("Error in encoding json")
	}
}

var t, token xml.Token
var err error
func xmltest() {
	input := "<Person><FirstName>Laura</FirstName><LastName>Lynn</LastName></Person>"
	inputReader := strings.NewReader(input)
	p := xml.NewDecoder(inputReader)

	for t, err = p.Token(); err == nil; t, err = p.Token(){
		switch token := t.(type) {
		case xml.StartElement:
			name := token.Name.Local
			fmt.Printf("Token name: %s\n", name)
			for _, attr := range token.Attr{
				attrName := attr.Name.Local
				attrValue := attr.Value
				fmt.Printf("An attribute is: %s %s\n", attrName, attrValue)
			}
		case xml.EndElement:
			fmt.Println("End of token")
		case xml.CharData:
			content := string([]byte(token))
			fmt.Printf("This is the content: %v\n", content)
		default:

		}
	}
}

type P struct {
	X, Y, Z int
	Name    string
}

type Q struct {
	X, Y *int
	Name  string
}

func gobtest1() {
	var network bytes.Buffer
	enc := gob.NewEncoder(&network)
	dec := gob.NewDecoder(&network)
	err := enc.Encode(P{3, 4, 0, "Pythagoras"})
	if err != nil{
		log.Fatal("encode error: ", err)
	}

	var q Q
	err = dec.Decode(&q)
	if err != nil {
		log.Fatal("decode error: ", err)
	}

	fmt.Printf("%q: {%d,%d}\n", q.Name, *q.X, *q.Y)
}

var content string

func gobtest2() {
	pa := &Address{"private", "Aartselaar", "Belgium"}
	wa := &Address{"work", "Boom", "Belgium"}
	vc := VCard{"Jan", "Kersschot", []*Address{pa, wa}, "none"}

	file, _ := os.OpenFile("G:\\golang\\waytogo\\readAndwrite\\vcard.gob", os.O_CREATE|os.O_WRONLY, 0666)
	defer file.Close()

	enc := gob.NewEncoder(file)
	err := enc.Encode(vc)
	if err != nil{
		log.Println("Error in encoding gob")
	}
}

func degobtest() {
	file, _ := os.Open("G:\\golang\\waytogo\\readAndwrite\\vcard.gob")
	defer file.Close()

	var vc VCard
	dec := gob.NewDecoder(file);
	err := dec.Decode(&vc)
	if err != nil{
		log.Println("Error in decoding gob")
	}

	fmt.Println(vc)
}

func hash_sha1_test() {
	hasher := sha1.New()
	io.WriteString(hasher, "test")
	b := []byte{}

	fmt.Printf("Result: %x\n", hasher.Sum(b))
	fmt.Printf("Result: %d\n", hasher.Sum(b))
	fmt.Printf("Result: %x\n", hasher.Sum(b))
	fmt.Printf("Result: %x\n", hasher.Sum(b))
	hasher.Reset()

	data := []byte("We shall overcome!")
	n, err := hasher.Write(data)
	if n != len(data) || err != nil{
		log.Printf("Hash write error: %v / %v", n, err)
	}

	checksum := hasher.Sum(b)
	fmt.Printf("Result: %x\n", checksum)
}

func main() {
	//test1()
	//test2()
	//test3()

	//fileInput()
	//test4()
	//test5()
	//test6()
	//test7()
	//argstest()
	//flagecho()

	//jsontest()
	//xmltest()
	//gobtest1()
	//gobtest2()
	//degobtest()
	hash_sha1_test()
}
